home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / viewers / gif / user.not < prev   
Text File  |  1988-02-06  |  11KB  |  174 lines

  1.  
  2. WHAT YOU GET
  3.  
  4.      The .ARC file you got should contain the following files:
  5.  
  6.      This USER.NOT file
  7.      GIFSLOW.PAS
  8.      GIFEGA.PAS
  9.      NLZW.ASM
  10.      READRAST.ASM
  11.      SCROLL.ASM
  12.      SCRSAVE.ASM
  13.      GIFSLOW.EXE
  14.      GIFEGA.EXE
  15.  
  16.      These make up the source and executable for two GIF reader/displayers
  17. written in Turbo Pascal 4.0 and MASM compatible assembly language. GIFSLOW
  18. is written entirely in Turbo to lay out the techniques being used in a form
  19. more accessible than assembly language, and boy, does it live up to its
  20. name -- you can go have a short beer while the program is decoding and
  21. displaying a single picture. GIFEGA is much faster -- it takes about 15-30
  22. seconds to display a picture depending on its complexity -- and adds a
  23. directory display, scrolling, and a file save feature. The guts of GIFEGA
  24. are in assembly-language external files, which I've tuned to make it as
  25. fast as I can manage. The principal reason for putting up these amateur
  26. works is to provide source code for LZW decompression, which seems to be a
  27. stumbling block for many who'd otherwise be writing their own GIF readers.
  28.      Using the program is pretty straightforward. With GIFSLOW all you do
  29. is type in the filename at the prompt. If you get tired of waiting for the
  30. picture to fully display, hitting ESC will get you out of it. GIFEGA is a
  31. little more sophisticated. The program will display a list of eligible
  32. files (files with the extension '.GIF') in the current directory. You're
  33. then prompted for a filename. Just hitting ENTER at this point gets you out
  34. of the program. Type in a single '\' character and the program will prompt
  35. you for a new path name, then switch to that new path and display a new
  36. list of files. Type in the filename you'd like to see displayed (you don't
  37. have to add the .GIF extension), and the program will display it. When the
  38. display is done, the computer will beep. If the picture is larger
  39. vertically than the screen, you can then scroll it by using the Up and Down
  40. Arrows and the Home and End keys. The Up and Down arrow keys move the
  41. picture in increments of ten scan lines at a time. The Home key moves to
  42. the top of the picture, and the End key moves to the bottom. Hitting ESC
  43. gets you out of the display and produces a prompt asking you to hit the
  44. space bar if you want to save the file as an EGA Paint compatible .SCR
  45. file. Hit the space bar and you'll save the file with the same pathname and
  46. filename but the extension .SCR. That's all there is to it.
  47.  
  48. HOW THE PROGRAM WORKS
  49.  
  50.      While the operation of the program is pretty fully explained in the
  51. comments, a brief sketch of its operation and a few notes on the techniques
  52. used are probably useful. The program starts by getting and sorting the
  53. directory list, displaying it, and then getting the filename from the user.
  54. The file is then read in, and it's worth spending a few moments on how we
  55. do this.
  56.      Since a GIF file has a header of no fixed length, the obvious way to
  57. treat it is as a file of byte. The problem is that reading long files a
  58. byte at a time in Turbo is a very slow process; if we cheat the compiler a
  59. bit by claiming that the file is really a single large data structure, and
  60. try to read it all in one fell swoop, we can speed matters up enormously.
  61.      This is what both programs do. The file is declared as a RasterArray,
  62. a one-dimensioned array of 64,000 bytes, which is maintained on the heap.
  63. We try to read this big data structure from the file. This demands that we
  64. turn off I/O checking during the read (otherwise if the file is smaller
  65. than 64,000 bytes an error will occur) and call IORESULT after the read (or
  66. else Turbo will refuse to do any more I/O). If the file is larger than
  67. 64,000 bytes, this will be detected and dealt with later.
  68.      Now we have the whole file, or most of it, in memory, and we have to
  69. read the header. This is done by the functions GetByte and GetWord, which
  70. mimic a file read of a single byte or of a word. We read the necessary
  71. variables described in the GIF spec from the file, and compute some more
  72. based on those. As described in 'Problems and Limitations' below we don't
  73. cope with absolutely every possibility outlined in the GIF spec, but I've
  74. yet to have the program fail on this account (although making the program
  75. conform completely to the spec is one obvious enhancement). We also read
  76. and set up the color palette. At this point, if it's a 256-color picture,
  77. we do an extremely crude fix to make the picture display in 16 colors with
  78. (hopefully) some remote resemblance to the original. This is done by
  79. arbitrarily declaring the first 16 colors in the palette to be the EGA
  80. palette, then resetting the color values above 16 to their nearest
  81. equivalents below 16. This could be improved on, and I'm open to
  82. suggestions as to how.
  83.      Once we have the necessary variables and constants all set up, we're
  84. ready to start decompressing. The first step in this is to unblock the
  85. whole data stream -- that is, to turn the data stream from a series of 255-
  86. byte or less blocks into one long stream of data. This may seem to be an
  87. unnecessary step; a lot of GIF readers seem to unblock the data stream as
  88. they go, but if we do that then each and every time we read a code we have
  89. to check to see if we're near the end of the current block, and if so, move
  90. the tail end of that block up to the front of the read buffer, unblock and
  91. add on the next block, and recompute BITOFFSET to point back to the start
  92. of the buffer. This makes for an awful lot of checking and computation
  93. repeated God knows how many times. Unblocking the data stream beforehand
  94. makes the READCODE routine much simpler, whether in high level or in
  95. assembly, and faster as well. (And why Compuserve decided to block the durn
  96. thing beats me: tradition?)
  97.      During unblocking we also cope with files larger than 64,000 bytes.
  98. The logic of this is simple enough: if we run out of GIFSTUFF during
  99. unblocking, we allocate memory for another RASTER array, do another read
  100. from the file, and put the rest of the data stream into this second RASTER
  101. array. During decoding, if this second array exists, we check to see if
  102. we're near the end of the first one. If so, we move the end of the first
  103. one up to the front of it, copy the contents of the second RASTER array
  104. into the first, reset BITOFFSET back to the start of the array, and keep
  105. on. This is just what other readers do on a block-by-block basis, but done
  106. on a larger scale, and only once. You can see this happen on a file bigger
  107. than 64,000 bytes: there'll be a 'hiccup' when the arrays are readjusted.
  108. This is faster than waiting and doing a second file read during the actual
  109. decompress/display, but as a consequence the program uses a lot of memory:
  110. as much as 192K over and above the size of the program at peak.
  111.      Once we have our data stream unblocked we can unravel the LZW
  112. decompression. This, frankly, I don't understand too well, but what comes
  113. out of the decompression cycle are pixels ready to write to the EGA screen.
  114. GIFSLOW does this a pixel at a time using a BIOS call; GIFEGA does this a
  115. scan line at a time, writing directly to EGA memory. We take advantage of
  116. the fact that the EGA's memory will hold a 640x480 picture (even if the
  117. card will only display 640x350) to get the whole picture into EGA memory,
  118. so that when we're done we can grab the four bit planes and save them in
  119. new heap arrays. We can then use those heap arrays to scroll the picture or
  120. save it as an EGA Paint-compatible .SCR file (which consists of the header
  121. followed by the four bit planes in order 0,2,1,3). Scrolling is done only
  122. if the picture is larger than the screen, and is done by using Write Mode 0
  123. to move the bitplanes from the heap arrays back into the EGA memory,
  124. starting at an an offset into the bitplane arrays determined by the Turbo
  125. variable ROLL. Originally the scrolling routine moved the bitplanes one at
  126. a time and all at a time, but this led to a 'rainbow' effect with some
  127. pictures (you could see the bitplanes being moved) and the routine was
  128. changed to move a scan line from each bitplane at a time, which got rid of
  129. the problem but allows you to see the scroll in action as the picture
  130. ripples down the screen. This could doubtless be improved.
  131.  
  132. LIMITATIONS AND KNOWN PROBLEMS
  133.  
  134.      The program deviates somewhat from the letter of the GIF spec, as
  135. follows:
  136.      No provision is made for a default colormap if a global one is not
  137. supplied.
  138.      No provision is made for dealing with a local colormap.
  139.      No provision is made for dealing with GIF enhancements, nor with
  140. multiple images in the same file.
  141.      While all these are deviations from the strict spec, I've yet to have
  142. the program fail on that account.
  143.      The program doesn't cope well with 256-color images. This is doubtless
  144. fixable (and one obvious area for improvement) but I haven't spent much
  145. time on it.
  146.      No provision is made in the program for modes other than vanilla EGA
  147. (640x350x16). One consequence of this is that though the save routine can
  148. write .SCP (640x480) files as well as .SCR files, this feature is
  149. permanently turned off in the program as it stands. This can be fixed, if
  150. you have an EGA that will handle more resolution, by changing the typed
  151. constant EGAHeight to 480.
  152.      The program doesn't work with GRABEGA; the files produced seem to have
  153. the wrong palette setting. Since GRABEGA works with other GIF readers the
  154. bug would seem to be in GIFEGA, but I don't know where, and since the
  155. program incorporates a .SCR save routine I'm not looking too hard.
  156.  
  157.      Some obvious areas of enhancement would include: more comprehensive
  158. error checking and recovery (at present the program will lock up or
  159. otherwise die if there's an error in the GIF data stream; detecting these
  160. is tough), printing, a sexier directory display with moving highlights,
  161. more save file formats, etc. More professional programmers would doubtless
  162. like more modularity and structure, less reliance on globals, and so on, in
  163. the code; anyone is welcome to dive in and improve the program any way he
  164. or she can.
  165.  
  166.      I hope you enjoy the program; I had fun writing it, and I hope you
  167. have fun with it. The code is placed in the public domain, since it's based
  168. on the work of others who were generous enough to place their code in the
  169. public domain; chief among these is Tom Pfau of DEC, who wrote the public
  170. domain file unsqueezer LZDCMP, on which this program is based. While I've
  171. claimed no copyright and you can do what you like with the code, it's
  172. intended for the use of individuals for their own enjoyment, and I ask that
  173. you don't use it in any program transferred for a fee.
  174.